﻿using Microsoft.Extensions.Options;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace Bridge.Shared.Redis
{
    public class RedisConnectionWrapper : IRedisConnectionWrapper
    {
        private bool _disposed;
        private readonly Lazy<string> _connectionString;
        private volatile ConnectionMultiplexer _connection;
        private readonly RedisConfiguration _redisConnectionConfiguration;

        public RedisConnectionWrapper(IOptions<RedisConfiguration> redisConnectionWrapper)
        {
            _redisConnectionConfiguration = redisConnectionWrapper.Value;
            _connectionString = new Lazy<string>(GetConnectionString);
        }

        protected string GetConnectionString()
        {
            return _redisConnectionConfiguration.Configuration;
        }
        protected EndPoint[] GetEndPoints()
        {
            var connection = GetConnection();

            return connection.GetEndPoints();
        }
        protected async Task<ConnectionMultiplexer> GetConnectionAsync()
        {
            if (_connection != null && _connection.IsConnected)
                return _connection;

            //Connection disconnected. Disposing connection...
            _connection?.Dispose();

            //Creating new instance of Redis Connection
            _connection = await ConnectionMultiplexer.ConnectAsync(_connectionString.Value);

            return _connection;
        }
        protected ConnectionMultiplexer GetConnection()
        {
            if (_connection != null && _connection.IsConnected)
                return _connection;

            //Connection disconnected. Disposing connection...
            _connection?.Dispose();

            //Creating new instance of Redis Connection
            _connection = ConnectionMultiplexer.Connect(_connectionString.Value);

            return _connection;
        }
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (_disposed)
                return;

            if (disposing)
            {
                //dispose ConnectionMultiplexer
                _connection?.Dispose();
            }
            _disposed = true;
        }

        public IDatabase GetDatabase(int db)
        {
            var connection = GetConnection();

            return connection.GetDatabase(db);
        }

        public async Task<IDatabase> GetDatabaseAsync(int db)
        {
            var connection = await GetConnectionAsync();

            return connection.GetDatabase(db);
        }

        public async Task<EndPoint[]> GetEndPointsAsync()
        {
            var connection = await GetConnectionAsync();

            return connection.GetEndPoints();
        }

        public async Task<IServer> GetServerAsync(EndPoint endPoint)
        {
            var connection = await GetConnectionAsync();

            return connection.GetServer(endPoint);
        }
    }
}
